\section{Metodyka}

Kiedy autor tej książki uczył się C, a później \Cpp, pisał tylko niewielkie kawałki kodu, kompilował i patrzył jak wyglądają w assemblerze. Tak było o wiele łatwiej zrozumieć co się dzieje w programie.%
\footnote{Szczerze mówiąc, dalej tak robi, kiedy nie rozumie jak jakiś kod działa.}.
Robił to wystarczająco dużą ilość razy, żeby związek między kodem w \CCpp a tym co generuje kompilator wbił się w jego podświadomość bardzo głęboko. Po tym, patrząc na kod w assemblerze, od razu ogólnikowo rozumiał to co było napisane w C. Możliwe, że to pomoże komuś jeszcze.

%Tu jest dużo przykładów do x86/x64 zarówno jak i do ARM.
%Ci którzy są wystarczająco dobrze obeznani z jedną z architektur, mogą pomijać te fragmenty.

Czasami będą wykorzystywane stare kompilatory, żeby otrzymać bardzo krótki lub prosty kawałek kodu.

A propos, jest jedna dobra strona, gdzie można robić wszystko to samo z różnymi kompilatorami bez konieczności instalowania ich u siebie: \url{http://gcc.beta.godbolt.org/}.

\section*{\Exercises}

Kiedy autor tej książki uczył się assemblera, on również często kompilował krótkie funkcje w C i powoli przepisywał je na assembler, mając na celu otrzymanie jak najkrótszego kodu. Możliwe, że nie jest to obecnie niezbędne jako że współczesne kompilatory optymalizują kod najbardziej jak się da, ale jest to bardzo dobry sposób, żeby oswoić się z assemblerem. Także możecie wziąć dowolny fragment kodu w assemblerze z tej książki i postarać się zrobić go krótszym. Warto nie zapominać o testowaniu wyników.

\section*{Poziomy optymalizajci i debuggowanie}

Kod źródłowy można kompilować różnymi kompilatorami z różnym poziomami optymalizacji. W typowym kompilatorze jest tych poziomów około trzech, gdzie poziom zerowy oznacza wyłączoną optymalizację. Rozróżnia się także kierunki optymalizacji według rozmiaru i poziomu prędkości. Niezoptymalizujący kompilator działa szybciej i generuje bardziej przejrzysty kod (choć i większy objętościowo). Optymalizujący kompilator działa wolniej i stara się wygenerować jak najszybszy kod (co nie zawsze znaczy, że kod będzie krótszy). Obok poziomów i kierunków optymalizacji kompilator może załączać do pliku wyniki debuggowania, tworząc w ten sposób kod, który jest prostszy w debuggowaniu. Bardzo ważną cechą kodu debuggowanego jest to, że zawiera on związki między każdą linią kodu źródłowego i adresem w kodzie maszynowym. Optymalizujące kompilatory zwykle generują kod, gdzie całe linie kodu źródłowego mogą zostać pominięte. Praktykujący reverse engineer z reguły ma styczność z obiema wersjami, jako że niektórzy developerzy włączają optymalizację, a niektórzy - nie. Dlatego postaramy się ćwiczyć rozważając obie możliwości.

